/***
 *npatomic_arm.cpp
 **************************************************************************************/
#ifdef __arm__
#include <stdio.h>
#include "npsync.h"
#include "npatomic.h"
#include "OSRawLock.h"

class ALocker
{
public:
	ALocker()
	{
	}
	virtual ~ALocker()
	{
	}
	virtual void Lock()
		{	m_lock.Lock();	}
	virtual void Unlock()
		{	m_lock.Unlock();	}

private:
	COSRawLock m_lock;
};
static inline ALocker& GetALocker()
{
	static ALocker obj;
	return obj;
}

long InterlockedExchange(long volatile* pVal, long newVal)
{
	long old;
	GetALocker().Lock();
	old = *pVal;
	*pVal = newVal;
	GetALocker().Unlock();
	return old;
}

long InterlockedExchangeAdd(long volatile* pVal, long addVal)
{
	long result;
	GetALocker().Lock();
	result = *pVal;
	*pVal += addVal;
	GetALocker().Unlock();
	return result;
}

long InterlockedCompareExchangeLong(long volatile* pVal, long newVal, long compareVal)
{
	long ret;
	GetALocker().Lock();
	ret = *pVal;
	if (*pVal == compareVal)
		*pVal = newVal;
	GetALocker().Unlock();
	return ret;
}

long InterlockedIncrement(long volatile* pVal)
	{	return InterlockedExchangeAdd(pVal, 1)+1;	}

long InterlockedDecrement(long volatile* pVal)
	{	return InterlockedExchangeAdd(pVal, -1)-1;	}

SLListNode* InterlockedSLListPush(SLList volatile* sl, SLListNode* newNode)
{
	STATIC_ASSERT(sizeof(void*) == sizeof(long));
	ASSERT(sl && newNode);
	SLListNode* old_head;
	do
	{
		old_head = sl->head;
		newNode->next = old_head;
	} while((long)old_head != InterlockedCompareExchangeLong((long*)(void*)&sl->head, (long)newNode, (long)old_head));
	return old_head;
}

SLListNode* InterlockedSLListPop(SLList volatile* sl)
{
	ASSERT(sl);
	SLListNode* old_head;
	SLListNode* next;
	do
	{
		old_head = sl->head;
		if(NULL == old_head)
			break;
		next = old_head->next;
	} while((long)old_head != InterlockedCompareExchangeLong((long*)(void*)&sl->head, (long)next, (long)old_head));
	return old_head;
}

#endif /*__arm__*/
